-
-
Notifications
You must be signed in to change notification settings - Fork 30.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-118423: Add INSTRUCTION_SIZE
macro to code generator
#125467
Conversation
cc @iritkatriel since you asked for this in #118380 (comment) :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really close to what I was thinking of. Great work!
inst: Instruction | None | ||
) -> bool: | ||
"""Replace the INSTRUCTION_SIZE macro with the size of the current instruction.""" | ||
size = inst.size if inst else 1 + uop.size |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tier2 does not have access to the instruction here so I calculate the size as 1 + uop.size
. Does that make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry this seems wrong, you need to emit the 1 + inline cache size not uop size
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I see when comparing the output of generated_cases.c.h
with executor_cases.c.h
that the latter has the wrong instruction size. I fixed it (I think) by looking up the instructions for each uop
in tier2 and passing it to the emitter.
Let me know if it's correct like that :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
INSTRUCTION_SIZE
is the size of the tier 1 instruction. This must be true even in tier 2.
I fixed it (I think) by looking up the instructions for each uop in tier2 and passing it to the emitter.
That is correct, but it would be nice if we also checked that all matching tier 1 instructions are the same size.
It looks like there are not tests for tier2 yet so I only added tests for tier1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this.
The general approach looks good, but I think we need to check that all the instructions containing the uop with INSTRUCTION_LENGTH
are the same length.
} | ||
""" | ||
self.run_cases_test(input, output) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a test for another instruction that is a different length, but uses OP
:
macro(OP2) = unused/1 + OP;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That test should fail, as the INSTRUCTION_SIZE
is inconsistent.
The tier 2 INSTRUCTION_SIZE
cannot be both 1 and 2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, sorry I mistakenly thought it should only fail for tier 2 hence I was only checking the instruction in the tier 2 generator. I extended the check to tier 1 as well and the test now fails as expected.
@@ -167,7 +167,7 @@ def oparg( | |||
return True | |||
|
|||
|
|||
def write_uop(uop: Uop, emitter: Emitter, stack: Stack) -> Stack: | |||
def write_uop(uop: Uop, emitter: Emitter, stack: Stack, inst: Instruction | None) -> Stack: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe pass the size, not the instruction. A uop can occur in many instructions, so picking one is arbitrary.
However, if it uses INSTRUCTION_SIZE
, than all instructions must be the same size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the check for the instruction size, which actually pointed out one place where we cannot use INSTRUCTION_SIZE
instead of next_instr - this_instr
:
Line 4799 in d8c8648
frame->return_offset = (uint16_t)(next_instr - this_instr); |
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
I also thought it was less than ideal the way I did it, but I was a bit wary about adding more attributes to the classes. Though, your suggestion simplifies the code quite a bit! I added a new attribute |
Friendly ping @markshannon 🙂 I think I addressed all of your points. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assertion needs to be changed to explicitly raise. Otherwise it won't work with -O
enabled.
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
Thanks again for the review! I have made the requested changes; please review again 🙂 |
Thanks for making the requested changes! @markshannon: please review the changes made to this pull request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good and correct now. Thanks.
I have a few suggestions, but they are mostly cosmetic.
if uop in inst.parts: | ||
if size is None: | ||
size = inst.size | ||
if size != inst.size: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if size != inst.size: | |
elif size != inst.size: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this to an if
because otherwise mypy complains that the elif
is unreachable:
Tools/cases_generator/analyzer.py:1103: error: Statement is unreachable [unreachable]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, leave it then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
Thanks for doing this.
Thanks for all the reviews! :) |
I am not that familiar with the tier 1 interpreter (yet 😄 ) so I'd appreciate if someone could double check that for all
the places that use the new
INSTRUCTION_SIZE
macro, it is actually safe to do so.I replaced all examples of
next_instr - this_instr
. There are still a few examples of1 + INLINE_CACHE_ENTRIES_...
but I wasn't sure whether those were safe to change as well.I named the new macro
INSTRUCTION_SIZE
, but I'm happy to change it toINSTRUCTION_LENGTH
if you prefer.Feedback welcome :)
INSTRUCTION_SIZE
macro to code generator. #118423